﻿/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is tyzoh.jp code.
 *
 * The Initial Developer of the Original Code is Kazutaka Kurihara.
 * Portions created by the Initial Developer are Copyright (C) 2007
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */
using System;
using System.Drawing;
using System.Windows.Forms;
using Qurihara.Anm;
using System.Drawing.Drawing2D;

namespace Qurihara
{
	/// <summary>
	/// View の概要の説明です。
	/// </summary>
	public class View : IAnmElement
	{
		public View(Size screenSiz)
		{
			viewRect = new Rectangle(0,0,screenSiz.Width,screenSiz.Height);
			screenSize = new Size(screenSiz.Width,screenSiz.Height);
			SetRatio();
		}

		public event EventHandler ViewChanged;

		protected bool isBusyMode = false;
		public bool IsBusyMode
		{
			get{return isBusyMode;}
			set{isBusyMode = value;}
		}
		protected Size screenSize;
		public Size ScreenSize
		{
			get{return screenSize;}
			set
			{
				screenSize = value;
				SetRatio();
                // 080623 ViewChangedはViewRectagleのみに作用すると思うのでコメントアウト
                //if (ViewChanged != null) ViewChanged(this,new EventArgs());
			}
		}
		protected Rectangle viewRect;
		public Rectangle ViewRectangle
		{
			get{return viewRect;}
			set{
				viewRect = value;
				SetRatio();
				if (ViewChanged != null) ViewChanged(this,new EventArgs());
			}
		}
		protected PointF screenToViewRatio = new PointF(0f,0f);
		public PointF ScreenToViewRatio
		{
			get{ return screenToViewRatio;}
		}
		protected PointF viewToScreenRatio = new PointF(0f,0f);
		public PointF ViewToScreenRatio
		{
			get{ return viewToScreenRatio;}
		}
		protected virtual void SetRatio()
		{
			screenToViewRatio.X = (float)viewRect.Width/(float)screenSize.Width;
			screenToViewRatio.Y = (float)viewRect.Height/(float)screenSize.Height;
			viewToScreenRatio.X = 1f / screenToViewRatio.X;
			viewToScreenRatio.Y = 1f / screenToViewRatio.Y;
		}

		public void ScreenToView(ref Point p)
		{
			p.X = viewRect.X + (int)(screenToViewRatio.X * p.X);
			p.Y = viewRect.Y + (int)(screenToViewRatio.Y * p.Y);
//			p.X = viewRect.X + p.X;
//			p.Y = viewRect.Y + p.Y;
		}
		public void ScreenToView(ref Point [] ps)
		{
			for(int i=0;i<ps.Length;i++) ScreenToView(ref ps[i]);
		}
		public void ScreenToView(ref Rectangle r)
		{
			Point tl = new Point(r.Left,r.Top);
			Point br = new Point(r.Right,r.Bottom);
			ScreenToView(ref tl);
			ScreenToView(ref br);
			r.Location = tl;
			r.Width = br.X -tl.X;
			r.Height = br.Y - tl.Y;
		}
		public void ViewToScreen(ref Point p)
		{
			p.X = (int)(viewToScreenRatio.X * (p.X - viewRect.X));
			p.Y = (int)(viewToScreenRatio.Y * (p.Y - viewRect.Y));
		}
		public void ViewToScreen(ref Point [] ps)
		{
			for(int i=0;i<ps.Length;i++) ViewToScreen(ref ps[i]);
		}
		public void ViewToScreen(ref Rectangle r)
		{
			Point tl = new Point(r.Left,r.Top);
			Point br = new Point(r.Right,r.Bottom);
			ViewToScreen(ref tl);
			ViewToScreen(ref br);
			r.Location = tl;
			r.Width = br.X -tl.X;
			r.Height = br.Y - tl.Y;
		}

		private Rectangle testRect = new Rectangle(0,0,0,0);
		public bool IsVisibleOnScreen(Rectangle rectByViewCoordinate)
		{
			return viewRect.IntersectsWith(rectByViewCoordinate);

			//簡易版．自分の２倍の大きさのものまで表示．
//			testRect.Location = viewRect.Location;
//			testRect.Size = viewRect.Size;
//			testRect.X -= rectByViewCoordinate.Width/2;
//			testRect.Width += rectByViewCoordinate.Width*2;
//			testRect.Y -= rectByViewCoordinate.Height/2;
//			testRect.Height += rectByViewCoordinate.Height*2;
//			//System.Console.WriteLine(testRect.X.ToString()+","+testRect.Y.ToString()+","+testRect.Width.ToString()+","+testRect.Height.ToString());
//			return testRect.Contains(rectByViewCoordinate);			

			//一部入っていればいいことにする。しかしこれでは以前と同様でかすぎるものは入らない。
//			return 
//				testRect.Contains(rectByViewCoordinate.Left,rectByViewCoordinate.Top) ||
//				testRect.Contains(rectByViewCoordinate.Right,rectByViewCoordinate.Top) ||
//				testRect.Contains(rectByViewCoordinate.Left,rectByViewCoordinate.Bottom) ||
//				testRect.Contains(rectByViewCoordinate.Right,rectByViewCoordinate.Bottom);

		}

		protected Matrix mm;
		protected Matrix wm;
		public void GraphicsTransform(Graphics g)
		{
			mm = new Matrix();
			wm = new Matrix();

			mm.Scale(viewToScreenRatio.X,viewToScreenRatio.Y);
			mm.Translate(-viewRect.X,-viewRect.Y);

//			//座標変換
//			//g.TranslateTransform(-viewRect.X,-viewRect.Y);
//			g.ScaleTransform(viewToScreenRatio.X,viewToScreenRatio.Y);
//			g.TranslateTransform(-viewRect.X,-viewRect.Y);

			g.Transform = mm;
			mm.Dispose();
		}

		public void GraphicsResume(Graphics g)
		{
			g.Transform = wm;
			wm.Dispose();
		}

		#region IAnmElement Implements
		public Rectangle BoundingBox
		{
			get{return viewRect;}
			set{this.ViewRectangle = value;}
		}
		public bool Visible
		{
			get{return true;}
			set{}
		}
		public void Invalidate()
		{
			// do nothing because button has autoredraw
		}
		public void Invalidate(Rectangle r)
		{
			// do nothing because button has autoredraw
		}
		private IAnm anm;
		public IAnm Anm
		{
			get{return anm;}
			set{anm = value;}
		}
		#endregion

	}
}
